package cloudContact.DAO;

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.WritableRaster;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import javax.imageio.ImageIO;

import sun.misc.IOUtils;

import com.google.gdata.client.Service.GDataRequest;
import com.google.gdata.data.Link;
import com.google.gdata.data.TextConstruct;
import com.google.gdata.data.contacts.Birthday;
import com.google.gdata.data.contacts.ContactEntry;
import com.google.gdata.data.contacts.GroupMembershipInfo;
import com.google.gdata.data.extensions.Email;
import com.google.gdata.data.extensions.ExtendedProperty;
import com.google.gdata.data.extensions.FamilyName;
import com.google.gdata.data.extensions.FullName;
import com.google.gdata.data.extensions.GivenName;
import com.google.gdata.data.extensions.Name;
import com.google.gdata.data.extensions.PhoneNumber;
import com.google.gdata.data.extensions.Where;
import com.google.gdata.util.ContentType;
import com.google.gdata.util.ResourceNotFoundException;
import com.google.gdata.util.ServiceException;

public class GoogleContact {

	public GoogleContact() {
		theEntry = new ContactEntry();
	}

	public GoogleContact(ContactEntry entry) {
		theEntry = entry;
	}

	final String NO_YOMI = null;

	public ArrayList<String> getGroups() {
		List<GroupMembershipInfo> groupInfos = theEntry
				.getGroupMembershipInfos();
		ArrayList<String> groupNames = new ArrayList<String>();

		for (GroupMembershipInfo membership : groupInfos) {
			// TODO: to get the name of the groups.
			groupNames.add(membership.getHref());
		}

		return groupNames;
	}

	public void setFullName(String name) {
		// TODO Auto-generated method stub
		Name cName = theEntry.getName();
		if (cName == null) {
			cName = new Name();
			theEntry.setName(cName);
		}
		cName.setFullName(new FullName(name, NO_YOMI));
	}

	public String getFullName() {
		// TODO Auto-generated method stub
		Name cName = theEntry.getName();
		if (cName == null) {
			return "No name";
		}
		return cName.getFullName().getValue();
	}

	public void setFirstName(String name) {
		Name cName = theEntry.getName();
		if (cName == null) {
			cName = new Name();
			theEntry.setName(cName);
		}
		cName.setGivenName(new GivenName(name, NO_YOMI));
	}

	public String getFirstName() {
		Name cName = theEntry.getName();
		if (cName == null) {
			return "No name";
		}
		return cName.getGivenName().getValue();
	}

	public void setLastName(String name) {
		Name cName = theEntry.getName();
		if (cName == null) {
			cName = new Name();
			theEntry.setName(cName);
		}
		cName.setFamilyName(new FamilyName(name, NO_YOMI));
	}

	public String getLastName() {
		Name cName = theEntry.getName();
		if (cName == null) {
			return "No name";
		}
		return cName.getFamilyName().getValue();
	}

	public void setMiddleName(String name) {
		Name cName = theEntry.getName();
		if (cName == null) {
			cName = new Name();
			theEntry.setName(cName);
		}
		// TODO: set the middle name in the entry
	}

	public String getMiddleName() {
		// TODO Auto-generated method stub
		return null;
	}

	public void setWorkPhone(String number) {
		setPhone("work", number);
	}

	public void setHomePhone(String number) {
		setPhone("home", number);
	}

	public void setMobilePhone(String number) {
		setPhone("mobile", number);
	}

	public String getWorkPhone() {
		PhoneNumber phone = getPhone("work");
		return phone == null ? "" : phone.getPhoneNumber();
	}

	public String getHomePhone() {
		PhoneNumber phone = getPhone("home");
		return phone == null ? "" : phone.getPhoneNumber();
	}

	public String getMobilePhone() {
		PhoneNumber phone = getPhone("mobile");
		return phone == null ? "" : phone.getPhoneNumber();
	}

	public String getEmail() {
		for (Email email : theEntry.getEmailAddresses()) {
			if (email.getRel().equals("http://schemas.google.com/g/2005#other")) {
				return email.getAddress();
			}
		}
		return "";
	}

	public void setEmail(String address) {
		for (Email email : theEntry.getEmailAddresses()) {
			if (email.getRel().equals("http://schemas.google.com/g/2005#other")) {
				email.setAddress(address);
				return;
			}
		}
		Email otherEmail = new Email();
		otherEmail.setAddress(address);
		otherEmail.setRel("http://schemas.google.com/g/2005#other");
		theEntry.addEmailAddress(otherEmail);
	}

	public Hashtable<String, String> getAllEmails() {
		Hashtable<String, String> emails = new Hashtable<String, String>();

		for (Email email : theEntry.getEmailAddresses()) {
			if (email != null && email.getRel() != null
					&& email.getAddress() != null) {
				emails.put(email.getRel(), email.getAddress());
			}
		}
		return emails;
	}

	public String getBirthday() {
		Birthday theBirthday = theEntry.getBirthday();
		return theBirthday == null ? "" : theBirthday.getWhen();

	}

	public void setBirthday(String birthday) {
		Birthday theBirthday = theEntry.getBirthday();
		if (theBirthday == null) {
			theBirthday = new Birthday();
			theEntry.setBirthday(theBirthday);
		}
		theBirthday.setWhen(birthday);
	}

	public String getContactId() {
		return theEntry.getId();
	}

	public void setContactId(String contactId) {
		theEntry.setId(contactId);
	}

	public String getAddress() {
		if (theEntry.hasWhere()) {
			return theEntry.getWhere().getValueString();
		}
		return "";
	}

	public void setAddress(String address) {
		Where where = new Where();
		where.setValueString(address);
		theEntry.setWhere(where);
	}

	public String getTitle() {
		TextConstruct title = theEntry.getTitle();
		return title.getPlainText();
	}

	public void setTitle(String tit) {
		TextConstruct title = TextConstruct.plainText(tit);
		theEntry.setTitle(title);
	}

	public String getLastSeenName() {
		ExtendedProperty property = this.getExtendedProperty("LastSeenName");
		return property == null ? "" : property.getValue();
	}

	public void setLastSeenName(String lastSeenName) {
		setExtendedProperty("lastSeenName", lastSeenName);
	}

	public float getLastSeenLati() {
		ExtendedProperty property = this.getExtendedProperty("LastSeenLati");
		return property == null ? 0 : Float.parseFloat(property.getValue());
	}

	public float getLastSeenLongi() {
		ExtendedProperty property = this.getExtendedProperty("LastSeenLongi");
		return property == null ? 0 : Float.parseFloat(property.getValue());
	}

	public void setLastSeenCoor(float lati, float longi) {
		setExtendedProperty("LastSeenLati", String.valueOf(lati));
		setExtendedProperty("LastSeenLongi", String.valueOf(longi));
	}

	public byte[] getImage() {
		if (theEntry.getService() == null) {

			System.out.println("Service is null.");

			return Image;
		}
		try {
			@SuppressWarnings("deprecation")
			InputStream in = theEntry.getService().getStreamFromLink(
					theEntry.getContactPhotoLink());
			// ByteArrayOutputStream out = new ByteArrayOutputStream();

			ByteArrayOutputStream buffer = new ByteArrayOutputStream();

			int nRead;
			byte[] data = new byte[4096];

			while ((nRead = in.read(data, 0, data.length)) != -1) {
				buffer.write(data, 0, nRead);
			}

			buffer.flush();

			Image = buffer.toByteArray();

			System.out.println("Image size is " + Image.length);

			return Image;
		} catch (ResourceNotFoundException e) {
			return null;
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (ServiceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}

	public void setImage(byte[] image) {
		Image = image;

		if (theEntry.getService() == null)
			return;
		// TODO: probably not work~
		URL photoUrl;
		try {
			Link photoLink = theEntry.getContactPhotoLink();
			photoUrl = new URL(photoLink.getHref());

			GDataRequest request = theEntry.getService().createRequest(
					GDataRequest.RequestType.UPDATE, photoUrl,
					new ContentType("image/jpeg"));

			request.setEtag(photoLink.getEtag());

			OutputStream requestStream = request.getRequestStream();
			requestStream.write(Image);

			request.execute();

		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ServiceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public String getExtension(String key) {
		ExtendedProperty eProperty = getExtendedProperty(key);
		if (eProperty == null)
			return "";
		else
			return eProperty.getValue();
	}

	public void setExtension(String key, String value) {
		setExtendedProperty(key, value);
	}

	public Hashtable<String, String> getAllExtensions() {
		Hashtable<String, String> allExtensions = new Hashtable<String, String>();
		for (int i = 0; i < theEntry.getExtendedProperties().size(); i++) {
			ExtendedProperty eProperty = theEntry.getExtendedProperties()
					.get(i);
			allExtensions.put(eProperty.getName(), eProperty.getValue());
		}
		return allExtensions;
	}

	public ContactEntry getTheEntry() {
		return theEntry;
	}

	public void setTheEntry(ContactEntry entry) {
		theEntry = entry;
	}

	public String getFacebookURL() {
		ExtendedProperty prop = getExtendedProperty("facebook");
		if (prop == null)
			return "";
		return prop.getValue();
	}

	public void setFacebookURL(String facebook) {
		setExtendedProperty("facebook", facebook);
	}

	public String getNotes() {
		ExtendedProperty prop = getExtendedProperty("notes");
		if (prop == null)
			return "";
		return prop.getValue();
	}

	public void setNotes(String notes) {
		setExtendedProperty("notes", notes);
	}

	private ExtendedProperty getExtendedProperty(String key) {
		for (int i = 0; i < theEntry.getExtendedProperties().size(); i++) {
			ExtendedProperty eProperty = theEntry.getExtendedProperties()
					.get(i);
			if (eProperty.getName().equals(key))
				return eProperty;
		}
		return null;
	}

	private void setExtendedProperty(String key, String value) {
		ExtendedProperty property = this.getExtendedProperty(key);
		if (property == null) {
			property = new ExtendedProperty();
			property.setName(key);
			theEntry.addExtendedProperty(property);
		}
		property.setValue(value);
	}

	private PhoneNumber getPhone(String relation) {
		for (int i = 0; i < theEntry.getPhoneNumbers().size(); i++) {
			PhoneNumber num = theEntry.getPhoneNumbers().get(i);
			if (num.getRel() == null)
				continue;
			if (num.getRel().equals(
					"http://schemas.google.com/g/2005#" + relation)) {
				return num;
			}
		}
		return null;
	}

	private void setPhone(String relation, String number) {
		PhoneNumber phone = getPhone(relation);
		if (phone == null) {
			phone = new PhoneNumber();
			phone.setRel("http://schemas.google.com/g/2005#" + relation);
			theEntry.addPhoneNumber(phone);
		}
		phone.setPhoneNumber(number);
	}

	private byte[] Image;

	private ContactEntry theEntry;

}